        (function () {

            var strategies = {
                half: function (option, width) {
                    return {
                        total: option.total * 2,
                        num: option.num * 2,
                        itemWidth: width / 2
                    }
                },
                entire: function (option, width) {
                    return {
                        total: option.total,
                        num: option.num,
                        itemWidth: width
                    }
                }
            };

            var Rating = function (elem, option) {
                this.$elem = $(elem);
                // 这里extend方法，如果option是false，则直接使用默认的对象，不会报错
                this.option = $.extend({}, Rating.defaultOption, option);
                var strategy = strategies[this.option.mode](this.option, 48);
                this.option.total = strategy.total;
                this.option.num = strategy.num;
                this.itemWidth = strategy.itemWidth;
            }
            Rating.prototype.init = function () {
                this.buildHtml();
                this.setCSS();
                this.lightOn(this.option.num);
                if (!this.option.readOnly) {
                    this.bindEvent();
                }
            };
            Rating.prototype.buildHtml = function () {
                var html = "";
                html += '<div class="rating-display"></div><ul class="rating-mask">';
                for (var i = 0; i < this.option.total; i++) {
                    html += '<li class="rating-item"></li>'
                }
                html += "</ul>";
                this.$elem.html(html);

            };
            Rating.prototype.setCSS = function () {
                this.$elem.width(this.option.total * this.itemWidth);
                this.$elem.find(".rating-item").width(this.itemWidth);
            };
            Rating.prototype.lightOn = function (num) {
                num = parseInt(num);
                this.$elem.find(".rating-display").css("width", (this.itemWidth * num) + "px");
            };
            Rating.prototype.bindEvent = function () {
                var self = this;
                this.$elem.on("mousemove", ".rating-item", function (event) {
                        var width = event.pageX - self.$elem.offset().left;
                        self.$elem.find(".rating-display").css("width", width + "px");

                        (typeof self.option.select === "function") && self.option.select.call(this, $(this)
                            .index() + 1, self.option.total);
                    })
                    .on("click", ".rating-item", function () {
                        self.option.num = $(this).index() + 1;
                        self.lightOn(self.option.num);

                        (typeof self.option.select === "function") && self.option.chosen.call(this, $(this)
                            .index() + 1, self.option.total);

                        self.$elem.trigger("chosen", [$(this).index + 1, self.option.total]);
                    })
                    .on("mouseout", ".rating-item", function () {
                        self.lightOn(self.option.num);
                    })
            };
            Rating.prototype.unBind = function () {
                this.$elem.off();
            };

            Rating.defaultOption = {
                total: 6,
                num: 3,
                readOnly: false,
                mode: "entire",
                select: function () {},
                chosen: function () {},
            }

            var init = function (elem, opt) {
                var rating;
                if ($(elem).data("rating")) {
                    rating = $(elem).data("rating");
                } else {
                    rating = new Rating(elem, (typeof opt === "object") && opt);
                    rating.$elem.data("rating", rating);
                    rating.init();
                }
                if (typeof opt === "string") {
                    rating[opt]();
                }
            }

            $.fn.extend({
                rating: function (opt) {
                    return $(this).each(function () {
                        init(this, opt);
                    });
                }
            })
        })();